home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Programming / MiniGL / src / draw.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-04-11  |  26.8 KB  |  885 lines

  1. /*
  2.  * $Id: draw.c,v 1.1.1.1 2000/04/07 19:44:51 hfrieden Exp $
  3.  *
  4.  * $Date: 2000/04/07 19:44:51 $
  5.  * $Revision: 1.1.1.1 $
  6.  *
  7.  * (C) 1999 by Hyperion
  8.  * All rights reserved
  9.  *
  10.  * This file is part of the MiniGL library project
  11.  * See the file Licence.txt for more details
  12.  *
  13.  */
  14.  
  15. #include "sysinc.h"
  16. #include <math.h>
  17. #include <stdlib.h>
  18.  
  19. static char rcsid[] = "$Id: draw.c,v 1.1.1.1 2000/04/07 19:44:51 hfrieden Exp $";
  20.  
  21. #define DUMP_VERTEX(vert) \
  22.  mykprintf("x:%6.3f y:%6.3f z:%6.3f w:%6.3f\nR:%6.3f G:%6.3f B:%6.3f A:%6.3f\nU:%6.3f V:%6.3f\noutcode=0x%x\n",\
  23.          vert.bx, vert.by, vert.bz, vert.bw,                                                                                      \
  24.          vert.v.color.r, vert.v.color.g, vert.v.color.b, vert.v.color.a,                                                          \
  25.          vert.v.u, vert.v.v, vert.outcode)
  26.  
  27. #define DUMP_VERTEX2(vert) \
  28.  mykprintf("X:%6.3f Y:%6.3f Z:%6.3f W:%6.3f\nR:%6.3f G:%6.3f B:%6.3f A:%6.3f\nU:%6.3f V:%6.3f\n",\
  29.          vert.x, vert.y, vert.z, vert.w,                                                                                  \
  30.          vert.color.r, vert.color.g, vert.color.b, vert.color.a,                                                          \
  31.          vert.u, vert.v);                                                                                                         \
  32.  
  33.  
  34. void d_DrawPoly(GLcontext context, MGLPolygon *poly);
  35. void dh_DrawPolyFF(GLcontext context, MGLPolygon *poly);
  36. void d_DrawPolyExt(GLcontext context, MGLPolygon *poly);
  37. void d_DrawPoints        (GLcontext);
  38. void d_DrawLines         (GLcontext);
  39. void d_DrawLineStrip     (GLcontext);
  40. void d_DrawTriangles     (GLcontext);
  41. void d_DrawTriangleFan   (GLcontext);
  42. void d_DrawTriangleStrip (GLcontext);
  43. void d_DrawQuads         (GLcontext);
  44. void d_DrawPolygon       (GLcontext);
  45. void d_DrawFlatFan       (GLcontext);
  46. void d_DrawQuadStrip     (GLcontext);
  47.  
  48. INLINE void v_ApplyMatrixElCheapo(GLcontext context, Matrix *pA, int vnum);
  49. INLINE GLvoid v_Transform(GLcontext context);
  50. INLINE void v_ToScreen(GLcontext context, int i);
  51. void m_CombineMatrices(GLcontext context);
  52.  
  53. extern void m_BuildInverted(GLcontext context);
  54. extern void hc_ClipAndDrawPolyFF(GLcontext context, MGLPolygon *poly, GLubyte or_codes);
  55.  
  56.  
  57. INLINE void v_ApplyMatrixElCheapo(GLcontext context, Matrix *pA, int vnum)
  58. {
  59.     // El Cheapo implementation ATM
  60.     #define a(x) (pA->v[OF_##x])
  61.     float x=context->VertexBuffer[vnum].bx;
  62.     float y=context->VertexBuffer[vnum].by;
  63.     float z=context->VertexBuffer[vnum].bz;
  64.     float w=context->VertexBuffer[vnum].bw;
  65.  
  66.     if (pA->flags == MGLMAT_IDENTITY) return;
  67.     context->VertexBuffer[vnum].bx = a(11)*x + a(12)*y + a(13)*z + a(14)*w;
  68.     context->VertexBuffer[vnum].by = a(21)*x + a(22)*y + a(23)*z + a(24)*w;
  69.     context->VertexBuffer[vnum].bz = a(31)*x + a(32)*y + a(33)*z + a(34)*w;
  70.     context->VertexBuffer[vnum].bw = a(41)*x + a(42)*y + a(43)*z + a(44)*w;
  71.  
  72.     return;
  73.     #undef a
  74. }
  75.  
  76.  
  77. INLINE void v_ApplyMatrixWOne(GLcontext context, Matrix *pA, int vnum)
  78. {
  79.     // W assumed to be 1.0
  80.     #define a(x) (pA->v[OF_##x])
  81.     float x=context->VertexBuffer[vnum].bx;
  82.     float y=context->VertexBuffer[vnum].by;
  83.     float z=context->VertexBuffer[vnum].bz;
  84.  
  85.     context->VertexBuffer[vnum].bx = a(11)*x + a(12)*y + a(13)*z + a(14);
  86.     context->VertexBuffer[vnum].by = a(21)*x + a(22)*y + a(23)*z + a(24);
  87.     context->VertexBuffer[vnum].bz = a(31)*x + a(32)*y + a(33)*z + a(34);
  88.     context->VertexBuffer[vnum].bw = a(41)*x + a(42)*y + a(43)*z + a(44);
  89.  
  90.     return;
  91.     #undef a
  92. }
  93.  
  94.  
  95. /*
  96. ** This computationally intensive piece of code generates coordinates
  97. ** for the reflective image used in spherical environment mapping.
  98. ** This is a good place for optimizations.
  99. ** After generation, transforms into the clipping space...
  100. **
  101. ** Note that this is after the book. It is probably a big time-eater.
  102. **
  103. ** (Turned out not to be so time intensive after all...)
  104. */
  105. void v_GenTexCoords(GLcontext context, int vertex)
  106. {
  107.     float u[4];
  108.     float ul;
  109.     float nx,ny,nz;
  110.     float nu;
  111.     float rx,ry,rz;
  112.     float m;
  113.     float s,t;
  114.  
  115.     if (context->InvRotValid == GL_FALSE) m_BuildInverted(context);
  116.  
  117.     #define a(x)    (CurrentMV->v[OF_##x])
  118.     #define b(x)    (CurrentP->v[OF_##x])
  119.     #define verx  (context->VertexBuffer[vertex].bx)
  120.     #define very  (context->VertexBuffer[vertex].by)
  121.     #define verz  (context->VertexBuffer[vertex].bz)
  122.     #define verw  (context->VertexBuffer[vertex].bw)
  123.  
  124.     u[0] = a(11)*verx + a(12)*very + a(13)*verz + a(14)*verw;
  125.     u[1] = a(21)*verx + a(22)*very + a(23)*verz + a(24)*verw;
  126.     u[2] = a(31)*verx + a(32)*very + a(33)*verz + a(34)*verw;
  127.     u[3] = a(41)*verx + a(42)*very + a(43)*verz + a(44)*verw;
  128.  
  129.     verx = b(11)*u[0] + b(12)*u[1] + b(13)*u[2] + b(14)*u[3];
  130.     very = b(21)*u[0] + b(22)*u[1] + b(23)*u[2] + b(24)*u[3];
  131.     verz = b(31)*u[0] + b(32)*u[1] + b(33)*u[2] + b(34)*u[3];
  132.     verw = b(41)*u[0] + b(42)*u[1] + b(43)*u[2] + b(44)*u[3];
  133.  
  134.     #undef a
  135.     #undef b
  136.     #undef verx
  137.     #undef very
  138.     #undef verz
  139.     #undef verw
  140.  
  141.     #define ver(c)  (context->VertexBuffer[vertex].Normal.c)
  142.     #define a(x)    (context->InvRot[x])
  143.  
  144.     // InvRot is row-major
  145.     nx = ver(x)*a(0) + ver(y)*a(3) + ver(z)*a(6);
  146.     ny = ver(x)*a(1) + ver(y)*a(4) + ver(z)*a(7);
  147.     nz = ver(x)*a(2) + ver(y)*a(5) + ver(z)*a(8);
  148.  
  149.     #undef ver
  150.     #undef a
  151.       
  152.  
  153.     if (u[3] != 1.f)
  154.     {
  155.     u[0] /= u[3]; u[1] /= u[3]; u[2] /= u[3];
  156.     }
  157.  
  158.     // nomalize unit vector
  159.     ul = (float)sqrt((double)(u[0]*u[0] + u[1]*u[1] + u[2]*u[2]));
  160.     if (ul == 0.f) return;
  161.     u[0] /= ul; u[1] /= ul; u[2] /= ul;
  162.  
  163.  
  164.     nu = nx*u[0] + ny*u[1]+nz*u[2]; nu *= 2.f;
  165.  
  166.     rx = u[0] - nx*nu;
  167.     ry = u[1] - ny*nu;
  168.     rz = u[2] - nz*nu;
  169.  
  170.  
  171.     m = 0.5f / (float)sqrt((double)(rx*rx + ry*ry + (rz+1.f)*(rz+1.f)));
  172.  
  173.     s = rx*m + 0.5;
  174.     t = ry*m + 0.5;
  175.  
  176.     if (context->TextureGenS_State == GL_TRUE)
  177.     {
  178.     context->VertexBuffer[vertex].v.u = context->w3dTexBuffer[context->CurrentBinding]->texwidth * s;
  179.     }
  180.     if (context->TextureGenT_State == GL_TRUE)
  181.     {
  182.     context->VertexBuffer[vertex].v.v = context->w3dTexBuffer[context->CurrentBinding]->texheight * t;
  183.     }
  184. }
  185.  
  186.  
  187. INLINE void v_Transform(GLcontext context)
  188. {
  189.     int i;
  190.  
  191.     if (context->TextureGenS_State == GL_TRUE || context->TextureGenT_State == GL_TRUE)
  192.     {
  193.     for (i=0; i<context->VertexBufferPointer; i++)
  194.     {
  195.         v_GenTexCoords(context, i);
  196.     }
  197.     }
  198.     else
  199.     {
  200.     if (context->CombinedValid == GL_FALSE)
  201.     {
  202.         m_CombineMatrices(context);
  203.     }
  204.     if (context->WOne_Hint == GL_FALSE)
  205.     {
  206.         for (i=0; i<context->VertexBufferPointer; i++)
  207.         {
  208.         v_ApplyMatrixElCheapo(context, &(context->CombinedMatrix), i);
  209.         }
  210.     }
  211.     else
  212.     {
  213.         for (i=0; i<context->VertexBufferPointer; i++)
  214.         {
  215.         v_ApplyMatrixWOne(context, &(context->CombinedMatrix), i);
  216.         }
  217.     }
  218.  
  219.     }
  220. }
  221.  
  222. INLINE void v_ToScreen(GLcontext context, int i)
  223. {
  224.     float w = 1.0 / context->VertexBuffer[i].bw;
  225.  
  226.     context->VertexBuffer[i].v.x = context->ax + context->VertexBuffer[i].bx * w * context->sx;
  227.     context->VertexBuffer[i].v.y = context->ay - context->VertexBuffer[i].by * w * context->sy;
  228.     context->VertexBuffer[i].v.z = context->az + context->VertexBuffer[i].bz * w * context->sz;
  229.     if (context->ZOffset_State == GL_TRUE)
  230.         context->VertexBuffer[i].v.z += (W3D_Float)context->ZOffset;
  231.     context->VertexBuffer[i].v.w = w;
  232. }
  233.  
  234. void d_DrawPoints(GLcontext context)
  235. {
  236. }
  237.  
  238. void d_DrawLines(GLcontext context)
  239. {
  240. }
  241.  
  242. void d_DrawLineStrip(GLcontext context)
  243. {
  244. }
  245.  
  246. #if 0
  247. void d_DumpPolygon(GLcontext context, MGLPolygon *poly)
  248. {
  249.     int i;
  250.     mykprintf("d_DumpPolygon: %d vertices\n", poly->numverts);
  251.     for (i=0; i<poly->numverts; i++)
  252.     {
  253.         DUMP_VERTEX(context->VertexBuffer[poly->verts[i]]);
  254.     }
  255.     mykprintf("-- \n");
  256. }
  257. #endif
  258.  
  259. void d_DrawTriangleFan(GLcontext context)
  260. {
  261.     int i;
  262.     GLubyte and_code, local_or, local_and;
  263.     ULONG error;
  264.     static W3D_Vertex **verts = NULL;
  265.     static GLboolean visible[MGL_MAXVERTS];     // Should be enough...?
  266.     static GLubyte   complete[MGL_MAXVERTS];    // Ditto
  267.     static W3D_TrianglesV tris;
  268.     int triangle = 0;
  269.  
  270.     if (verts == NULL)
  271.     {
  272.         verts = (W3D_Vertex **)malloc(sizeof(W3D_Vertex *) * context->VertexBufferSize);
  273.         if (!verts) return;
  274.     }
  275.  
  276.     v_Transform(context); // Transform world to clipping coordinates
  277.  
  278.     and_code = 0xFF;
  279.     for (i=0; i<context->VertexBufferPointer; i++)
  280.     {
  281.         hc_CodePoint(&(context->VertexBuffer[i]));
  282.         and_code &= context->VertexBuffer[i].outcode;
  283.     }
  284.  
  285.     if (and_code) return;
  286.  
  287.     /*
  288.     ** Up to now everything is like a polygon. Unlike a polygon, however,
  289.     ** triangle fans and strips may be concave, and each individual triangle
  290.     ** might be backfacing.
  291.     **
  292.     ** We calculate how many of the triangles are visible.
  293.     */
  294.     for (i=1,triangle=0; i<context->VertexBufferPointer - 1; i++, triangle++)
  295.     {
  296.         local_or = context->VertexBuffer[0].outcode
  297.             | context->VertexBuffer[i].outcode
  298.             | context->VertexBuffer[i+1].outcode;
  299.  
  300.         local_and = context->VertexBuffer[0].outcode
  301.             & context->VertexBuffer[i].outcode
  302.             & context->VertexBuffer[i+1].outcode;
  303.  
  304.         if (local_and == 0) // if the local and code is zero, we're not
  305.         {                   // completely off screen.
  306.             visible[triangle] = hc_DecideFrontface(context,
  307.                 &(context->VertexBuffer[0]),
  308.                 &(context->VertexBuffer[i]),
  309.                 &(context->VertexBuffer[i+1]), local_or);
  310.             // if our local or codes are zero, we are completely
  311.             // visible
  312.             complete[triangle] = local_or;
  313.         }
  314.         else
  315.         {
  316.             visible[triangle] = GL_FALSE;
  317.         }
  318.     }
  319.  
  320.     /*
  321.     ** Draw...
  322.     ** There are three cases:
  323.     **
  324.     ** 1) Triangle is partially visible
  325.     ** 2) Triangle is fully visible
  326.     ** 3) Triangle is invisible
  327.     **
  328.     ** In case 1, we draw the triangle with clip_ClipAndDrawPoly.
  329.     ** In case 2, we collect a triangle fan/strip of maximum length
  330.     ** and draw that directly
  331.     ** in case 3... WE IGNORE IT! HA!
  332.     */
  333.     triangle = 0; i=1;
  334.  
  335.     do
  336.     {
  337.         if (visible[triangle] == GL_FALSE) // case 3
  338.         {
  339.             triangle ++;
  340.             i        ++;
  341.         }
  342.         else
  343.         {
  344.             if (complete[triangle]) // case 1
  345.             {
  346.                 static MGLPolygon poly;
  347.                 poly.numverts = 3;
  348.                 poly.verts[0] = 0;
  349.                 poly.verts[1] = i;
  350.                 poly.verts[2] = i + 1;
  351.                 // HERE
  352.                 hc_ClipAndDrawPoly(context, &poly, complete[triangle] );
  353.                 triangle++;
  354.                 i++;
  355.             }
  356.             else
  357.             {   // case 2 (the difficult part)
  358.                 int k=3;
  359.                 tris.vertexcount = 3;
  360.                 verts[0] = &(context->VertexBuffer[0].v);
  361.                 verts[1] = &(context->VertexBuffer[i].v);
  362.                 verts[2] = &(context->VertexBuffer[i+1].v);
  363.                 v_ToScreen(context, 0);
  364.                 v_ToScreen(context, i);
  365.                 v_ToScreen(context, i+1);
  366.  
  367.                 triangle ++;
  368.                 i        ++;
  369.  
  370.                 while (complete[triangle]==0 && visible[triangle] && i<context->VertexBufferPointer - 1)
  371.                 {
  372.                     verts[k] = &(context->VertexBuffer[i+1].v);
  373.                     v_ToScreen(context, i+1);
  374.                     i++; k++; triangle++;
  375.                     tris.vertexcount ++;
  376.                 }
  377.                 tris.tex = context->w3dTexBuffer[context->CurrentBinding];
  378.                 tris.st_pattern = NULL;
  379.                 tris.v = verts;
  380.                 error = W3D_DrawTriFanV(context->w3dContext, &tris);
  381.                 if (error != W3D_SUCCESS) kprintf("W3D_DrawTriFan = %ld\n", error);
  382.  
  383.             }
  384.         }
  385.     } while (i<context->VertexBufferPointer-1);
  386.  
  387. }
  388.  
  389. void d_DrawTriangleStrip(GLcontext context)
  390. {
  391.     int i;
  392.     GLubyte and_code, local_or, local_and;
  393.     ULONG error;
  394.     static W3D_Vertex **verts = NULL;
  395.     static GLboolean visible[MGL_MAXVERTS];     // Should be enough...?
  396.     static GLubyte   complete[MGL_MAXVERTS];    // Ditto
  397.     static W3D_TrianglesV tris;
  398.     int triangle = 0;
  399.     GLenum CurrentFrontFace = context->CurrentFrontFace;
  400.  
  401.  
  402.  
  403.     if (verts == NULL)
  404.     {
  405.         verts = (W3D_Vertex **)malloc(sizeof(W3D_Vertex *) * context->VertexBufferSize);
  406.         if (!verts) return;
  407.     }
  408.  
  409.     v_Transform(context);
  410.  
  411.     and_code = 0xFF;
  412.     for (i=0; i<context->VertexBufferPointer; i++)
  413.     {
  414.         hc_CodePoint(&(context->VertexBuffer[i]));
  415.         and_code &= context->VertexBuffer[i].outcode;
  416.     }
  417.  
  418.     if (and_code) return;
  419.  
  420.     /*
  421.     ** Up to now everything is like a polygon. Unlike a polygon, however,
  422.     ** triangle fans and strips may be concave, and each individual triangle
  423.     ** might be backfacing.
  424.     **
  425.     ** We calculate how many of the triangles are visible.
  426.     */
  427.     for (i=0,triangle=0; i<context->VertexBufferPointer - 2; i++, triangle++)
  428.     {
  429.         local_or = context->VertexBuffer[i+0].outcode
  430.                  | context->VertexBuffer[i+1].outcode
  431.                  | context->VertexBuffer[i+2].outcode;
  432.  
  433.         local_and = context->VertexBuffer[i+0].outcode
  434.                   & context->VertexBuffer[i+1].outcode
  435.                   & context->VertexBuffer[i+2].outcode;
  436.  
  437.         if (local_and == 0) // if the local and code is zero, we're not
  438.         {                   // completely off screen.
  439.             visible[triangle] = hc_DecideFrontface(context,
  440.                 &(context->VertexBuffer[i+0]),
  441.                 &(context->VertexBuffer[i+1]),
  442.                 &(context->VertexBuffer[i+2]), local_or);
  443.             // if our local or codes are zero, we are completely
  444.             // visible
  445.             complete[triangle] = local_or;
  446.         }
  447.         else
  448.         {
  449.             visible[triangle] = GL_FALSE;
  450.         }
  451.  
  452.         if (context->CurrentFrontFace == GL_CCW) context->CurrentFrontFace = GL_CW;
  453.         else                                     context->CurrentFrontFace = GL_CCW;
  454.  
  455.     }
  456.     /*
  457.     ** Draw...
  458.     ** There are three cases:
  459.     **
  460.     ** 1) Triangle is partially visible
  461.     ** 2) Triangle is fully visible
  462.     ** 3) Triangle is invisible
  463.     **
  464.     ** In case 1, we draw the triangle with clip_ClipAndDrawPoly.
  465.     ** In case 2, we collect a triangle fan/strip of maximum length
  466.     ** and draw that directly
  467.     ** in case 3... WE IGNORE IT! HA!
  468.     */
  469.     triangle = 0; i=0;
  470.  
  471.     context->CurrentFrontFace = CurrentFrontFace;
  472.  
  473.     do
  474.     {
  475.  
  476.         if (visible[triangle] == GL_FALSE) // case 3
  477.         {
  478.             triangle ++;
  479.             i        ++;
  480.         }
  481.         else
  482.         {
  483.             if (complete[triangle]) // case 1
  484.             {
  485.                 static MGLPolygon poly;
  486.  
  487.                 poly.numverts = 3;
  488.                 poly.verts[0] = i + 0;
  489.                 poly.verts[1] = i + 1;
  490.                 poly.verts[2] = i + 2;
  491.  
  492.                 hc_ClipAndDrawPoly(context, &poly, complete[triangle] );
  493.                 triangle++;
  494.                 i++;
  495.             }
  496.             else
  497.             {   // case 2 (the difficult part)
  498.                 int k=3;
  499.                 tris.vertexcount = 3;
  500.                 verts[0] = &(context->VertexBuffer[i+0].v);
  501.                 verts[1] = &(context->VertexBuffer[i+1].v);
  502.                 verts[2] = &(context->VertexBuffer[i+2].v);
  503.                 v_ToScreen(context, i);
  504.                 v_ToScreen(context, i+1);
  505.                 v_ToScreen(context, i+2);
  506.                 triangle ++;
  507.                 i        ++;
  508.  
  509.                 while (complete[triangle]==0 && visible[triangle] && i<context->VertexBufferPointer - 2)
  510.                 {
  511.                     verts[k] = &(context->VertexBuffer[i+2].v);
  512.                     v_ToScreen(context, i+2);
  513.                     i++; k++;
  514.                     triangle++;
  515.                     tris.vertexcount ++;
  516.                 }
  517.  
  518.                 tris.tex = context->w3dTexBuffer[context->CurrentBinding];
  519.                 tris.st_pattern = NULL;
  520.                 tris.v = verts;
  521.                 error = W3D_DrawTriStripV(context->w3dContext, &tris);
  522.                 if (error != W3D_SUCCESS) kprintf("W3D_DrawTriStrip = %ld\n", error);
  523.  
  524.             }
  525.         }
  526.         if (context->CurrentFrontFace == GL_CCW) context->CurrentFrontFace = GL_CW;
  527.         else                                     context->CurrentFrontFace = GL_CCW;
  528.     } while (i<context->VertexBufferPointer - 2);
  529.  
  530.     context->CurrentFrontFace = CurrentFrontFace;
  531.  
  532. }
  533.  
  534. void d_DrawQuadStrip(GLcontext context)
  535. {
  536.     int i;
  537.     GLubyte or_code, and_code;
  538.     ULONG error;
  539.     static W3D_Vertex *verts[4];
  540.     static W3D_TrianglesV tris;
  541.  
  542.     v_Transform(context);
  543.  
  544.     for (i=0; i<context->VertexBufferPointer-2; i+=2)
  545.     {
  546.         hc_CodePoint(&(context->VertexBuffer[i]));
  547.         hc_CodePoint(&(context->VertexBuffer[i+1]));
  548.         hc_CodePoint(&(context->VertexBuffer[i+2]));
  549.         hc_CodePoint(&(context->VertexBuffer[i+3]));
  550.  
  551.         or_code = context->VertexBuffer[i+0].outcode
  552.                 | context->VertexBuffer[i+1].outcode
  553.                 | context->VertexBuffer[i+2].outcode
  554.                 | context->VertexBuffer[i+3].outcode;
  555.  
  556.         and_code = context->VertexBuffer[i+0].outcode
  557.                  & context->VertexBuffer[i+1].outcode
  558.                  & context->VertexBuffer[i+2].outcode
  559.                  & context->VertexBuffer[i+3].outcode;
  560.  
  561.         if (and_code) continue;
  562.  
  563.         if (hc_DecideFrontface(context, &(context->VertexBuffer[i]),
  564.             &(context->VertexBuffer[i+1]),
  565.             &(context->VertexBuffer[i+2]), or_code) == GL_FALSE) continue;
  566.  
  567.         if (or_code == 0)
  568.         {
  569.             v_ToScreen(context, i);
  570.             v_ToScreen(context, i+1);
  571.             v_ToScreen(context, i+2);
  572.             v_ToScreen(context, i+3);
  573.  
  574.             verts[0] = &(context->VertexBuffer[i+0].v);
  575.             verts[1] = &(context->VertexBuffer[i+1].v);
  576.             verts[2] = &(context->VertexBuffer[i+3].v);
  577.             verts[3] = &(context->VertexBuffer[i+2].v);
  578.             tris.tex = context->w3dTexBuffer[context->CurrentBinding];
  579.             tris.st_pattern = NULL;
  580.             tris.vertexcount = 4;
  581.             tris.v = verts;
  582.             if (context->ShadeModel == GL_FLAT)
  583.             {
  584.                 W3D_SetCurrentColor(context->w3dContext, &(context->VertexBuffer[i].v.color));
  585.             }
  586.  
  587.             error = W3D_DrawTriFanV(context->w3dContext, &tris);
  588.             if (error != W3D_SUCCESS) kprintf("W3D_DrawTriFan = %ld\n", error);
  589.         }
  590.         else
  591.         {
  592.             static MGLPolygon poly;
  593.             poly.numverts = 4;
  594.             poly.verts[0] = i;
  595.             poly.verts[1] = i+1;
  596.             poly.verts[2] = i+3;
  597.             poly.verts[3] = i+2;
  598.             if (context->ShadeModel == GL_FLAT)
  599.             {
  600.                 W3D_SetCurrentColor(context->w3dContext, &(context->VertexBuffer[i].v.color));
  601.             }
  602.             hc_ClipAndDrawPoly(context, &poly, or_code);
  603.         }
  604.     }
  605. }
  606.  
  607.  
  608. void d_DrawQuads(GLcontext context)
  609. {
  610.     int i;
  611.     GLubyte or_code, and_code;
  612.     ULONG error;
  613.     static W3D_Vertex *verts[4];
  614.     static W3D_TrianglesV tris;
  615.  
  616.  
  617.     v_Transform(context);
  618.  
  619.     for (i=0; i<context->VertexBufferPointer; i+=4)
  620.     {
  621.         hc_CodePoint(&(context->VertexBuffer[i]));
  622.         hc_CodePoint(&(context->VertexBuffer[i+1]));
  623.         hc_CodePoint(&(context->VertexBuffer[i+2]));
  624.         hc_CodePoint(&(context->VertexBuffer[i+3]));
  625.  
  626.         or_code = context->VertexBuffer[i+0].outcode
  627.                 | context->VertexBuffer[i+1].outcode
  628.                 | context->VertexBuffer[i+2].outcode
  629.                 | context->VertexBuffer[i+3].outcode;
  630.  
  631.         and_code = context->VertexBuffer[i+0].outcode
  632.                  & context->VertexBuffer[i+1].outcode
  633.                  & context->VertexBuffer[i+2].outcode
  634.                  & context->VertexBuffer[i+3].outcode;
  635.  
  636.         if (and_code) continue;
  637.  
  638.         if (hc_DecideFrontface(context, &(context->VertexBuffer[i]),
  639.             &(context->VertexBuffer[i+1]),
  640.             &(context->VertexBuffer[i+2]),or_code) == GL_FALSE) continue;
  641.  
  642.         if (context->ShadeModel == GL_FLAT)
  643.         {
  644.             W3D_SetCurrentColor(context->w3dContext, &(context->VertexBuffer[i].v.color));
  645.         }
  646.  
  647.         if (or_code == 0)
  648.         {
  649.             v_ToScreen(context, i);
  650.             v_ToScreen(context, i+1);
  651.             v_ToScreen(context, i+2);
  652.             v_ToScreen(context, i+3);
  653.  
  654.             verts[0] = &(context->VertexBuffer[i+0].v);
  655.             verts[1] = &(context->VertexBuffer[i+1].v);
  656.             verts[2] = &(context->VertexBuffer[i+2].v);
  657.             verts[3] = &(context->VertexBuffer[i+3].v);
  658.             tris.tex = context->w3dTexBuffer[context->CurrentBinding];
  659.             tris.st_pattern = NULL;
  660.             tris.vertexcount = 4;
  661.             tris.v = verts;
  662.             #ifndef NODRAW
  663.             error = W3D_DrawTriFanV(context->w3dContext, &tris);
  664.             if (error != W3D_SUCCESS) kprintf("W3D_DrawTriFan = %ld\n", error);
  665.             #else
  666.             printf("d_DrawQuads\n");
  667.             DUMP_VERTEX(context->VertexBuffer[i+0]);
  668.             DUMP_VERTEX(context->VertexBuffer[i+1]);
  669.             DUMP_VERTEX(context->VertexBuffer[i+2]);
  670.             DUMP_VERTEX(context->VertexBuffer[i+3]);
  671.             printf("-----------------------------------\n");
  672.             #endif
  673.             #if 1
  674.             if (error != W3D_SUCCESS) kprintf("[MiniGL::d_DrawQuads] Duh! Error %ld\n", error);
  675.             #endif
  676.         }
  677.         else
  678.         {
  679.             static MGLPolygon poly;
  680.             poly.numverts = 4;
  681.             poly.verts[0] = i;
  682.             poly.verts[1] = i+1;
  683.             poly.verts[2] = i+2;
  684.             poly.verts[3] = i+3;
  685.             hc_ClipAndDrawPoly(context, &poly, or_code);
  686.         }
  687.     }
  688. }
  689.  
  690. void d_DrawPolygon(GLcontext context)
  691. {
  692.     int i;
  693.     GLubyte or_code, and_code;
  694.     MGLPolygon poly;
  695.  
  696.     v_Transform(context);
  697.     or_code = 0; and_code = 0xFF;
  698.  
  699.     for (i=0; i<context->VertexBufferPointer; i++)
  700.     {
  701.         hc_CodePoint(&(context->VertexBuffer[i]));
  702.         or_code  |= context->VertexBuffer[i].outcode;
  703.         and_code &= context->VertexBuffer[i].outcode;
  704.         poly.verts[i] = i;
  705.     }
  706.  
  707.  
  708.     if (and_code) return;
  709.     #if 0
  710.     if (hc_DecideFrontface(context, &(context->VertexBuffer[0]),
  711.         &(context->VertexBuffer[1]),
  712.         &(context->VertexBuffer[2]),or_code) == GL_FALSE) return;
  713.     #endif
  714.  
  715.     poly.numverts = context->VertexBufferPointer;
  716.  
  717.     if (or_code == 0)
  718.     {
  719.         dh_DrawPolyFF(context, &poly);
  720.     }
  721.     else
  722.     {
  723.         hc_ClipAndDrawPolyFF(context, &poly, or_code);
  724.     }
  725. }
  726.  
  727. void d_DrawTriangles(GLcontext context)
  728. {
  729.     int i;
  730.     W3D_TriangleV tri;
  731.     GLubyte or_code, and_code;
  732.     ULONG error;
  733.  
  734.     v_Transform(context);
  735.  
  736.     for (i=0; i<context->VertexBufferPointer; i+=3)
  737.     {
  738.         hc_CodePoint(&(context->VertexBuffer[i]));
  739.         hc_CodePoint(&(context->VertexBuffer[i+1]));
  740.         hc_CodePoint(&(context->VertexBuffer[i+2]));
  741.  
  742.         or_code = context->VertexBuffer[i+0].outcode
  743.                 | context->VertexBuffer[i+1].outcode
  744.                 | context->VertexBuffer[i+2].outcode;
  745.  
  746.         and_code = context->VertexBuffer[i+0].outcode
  747.                  & context->VertexBuffer[i+1].outcode
  748.                  & context->VertexBuffer[i+2].outcode;
  749.         if (and_code) continue;
  750.  
  751.         if (hc_DecideFrontface(context, &(context->VertexBuffer[i]),
  752.             &(context->VertexBuffer[i+1]),
  753.             &(context->VertexBuffer[i+2]),or_code) == GL_FALSE) continue;
  754.  
  755.  
  756.         if (or_code == 0)
  757.         {
  758.             v_ToScreen(context, i);
  759.             v_ToScreen(context, i+1);
  760.             v_ToScreen(context, i+2);
  761.  
  762.             tri.v1 = &(context->VertexBuffer[i+0].v);
  763.             tri.v2 = &(context->VertexBuffer[i+1].v);
  764.             tri.v3 = &(context->VertexBuffer[i+2].v);
  765.             tri.tex = context->w3dTexBuffer[context->CurrentBinding];
  766.             tri.st_pattern = NULL;
  767.             error = W3D_DrawTriangleV(context->w3dContext, &tri);
  768.             if (error != W3D_SUCCESS) kprintf("W3D_DrawTriangle = %ld\n", error);
  769.         }
  770.         else
  771.         {
  772.             static MGLPolygon poly;
  773.             poly.numverts = 3;
  774.             poly.verts[0] = i;
  775.             poly.verts[1] = i+1;
  776.             poly.verts[2] = i+2;
  777.             hc_ClipAndDrawPoly(context, &poly, or_code);
  778.         }
  779.     }
  780. }
  781.  
  782. /*
  783. ** A FlatFan is a triangle fan that is specified in device corrdinates and
  784. ** is drawn regardless of current matrix or other
  785. */
  786. void d_DrawFlatFan(GLcontext context)
  787. {
  788.     ULONG error;
  789.     int i;
  790.     static W3D_Vertex *verts[MGL_MAXVERTS];
  791.     static W3D_TrianglesV tris;
  792.  
  793.     for (i=0; i<context->VertexBufferPointer; i++)
  794.     {
  795.         verts[i] = &(context->VertexBuffer[i].v);
  796.         context->VertexBuffer[i].v.x = (W3D_Float) context->VertexBuffer[i].bx;
  797.         context->VertexBuffer[i].v.y = (W3D_Float) context->VertexBuffer[i].by;
  798.         context->VertexBuffer[i].v.z = (W3D_Double)context->VertexBuffer[i].bz;
  799.         context->VertexBuffer[i].v.w = (W3D_Float) context->VertexBuffer[i].bw;
  800.     }
  801.     tris.tex = context->w3dTexBuffer[context->CurrentBinding];
  802.     tris.st_pattern = NULL;
  803.     tris.v = verts;
  804.     tris.vertexcount = context->VertexBufferPointer;
  805.     #ifndef NODRAW
  806.     error = W3D_DrawTriFanV(context->w3dContext, &tris);
  807.     if (error != W3D_SUCCESS) kprintf("W3D_DrawTriFanV = %ld\n", error);
  808.     #endif
  809. }
  810.  
  811. void dh_DrawPoly(GLcontext context, MGLPolygon *poly)
  812. {
  813.     int i;
  814.     ULONG error;
  815.     static W3D_Vertex *verts[MGL_MAXVERTS];
  816.     static W3D_TrianglesV tris;
  817.  
  818.     for (i=0; i<poly->numverts; i++)
  819.     {
  820.         v_ToScreen(context, poly->verts[i]);
  821.         verts[i] = &(context->VertexBuffer[poly->verts[i]].v);
  822.     }
  823.  
  824.     tris.tex = context->w3dTexBuffer[context->CurrentBinding];
  825.     tris.st_pattern = NULL;
  826.     tris.vertexcount = poly->numverts;
  827.     tris.v = verts;
  828.     #ifndef NODRAW
  829.     error = W3D_DrawTriFanV(context->w3dContext, &tris);
  830.     if (error != W3D_SUCCESS) kprintf("W3D_DrawTriFan = %ld\n", error);
  831.     #endif
  832. }
  833.  
  834. inline GLfloat dh_AreaSign(GLcontext context, MGLPolygon *poly)
  835. {
  836.     int i,j;
  837.     GLfloat area=0.0;
  838.     #define x(i) (context->VertexBuffer[poly->verts[i]].v.x)
  839.     #define y(i) (context->VertexBuffer[poly->verts[i]].v.y)
  840.  
  841.     for (i=0; i<poly->numverts; i++)
  842.     {
  843.         j=(i+1)%(poly->numverts);
  844.         area += (x(i)*y(j) - x(j)*y(i));
  845.     }
  846.  
  847.     #undef x
  848.     #undef y
  849.  
  850.     return area;
  851. }
  852.  
  853. void dh_DrawPolyFF(GLcontext context, MGLPolygon *poly)
  854. {
  855.     int i;
  856.     ULONG error;
  857.     static W3D_Vertex *verts[MGL_MAXVERTS];
  858.     static W3D_TrianglesV tris;
  859.     GLfloat area;
  860.  
  861.     for (i=0; i<poly->numverts; i++)
  862.     {
  863.         v_ToScreen(context, poly->verts[i]);
  864.         verts[i] = &(context->VertexBuffer[poly->verts[i]].v);
  865.     }
  866.  
  867.     if (context->CullFace_State == GL_TRUE)
  868.     {
  869.         area = dh_AreaSign(context, poly);
  870.  
  871.         if (context->CurrentFrontFace == GL_CW) area *= -1.f;
  872.         if (area < 0.0) return;
  873.     }
  874.  
  875.     tris.tex = context->w3dTexBuffer[context->CurrentBinding];
  876.     tris.st_pattern = NULL;
  877.     tris.vertexcount = poly->numverts;
  878.     tris.v = verts;
  879.     #ifndef NODRAW
  880.     error = W3D_DrawTriFanV(context->w3dContext, &tris);
  881.     if (error != W3D_SUCCESS) kprintf("W3D_DrawTriFan = %ld\n", error);
  882.     #endif
  883. }
  884.  
  885.